package com.jf.anmocker.plugin

import com.jf.anmocker.plugin.injector.AnoEntity
import com.jf.anmocker.plugin.injector.AMInjector
import com.jf.anmocker.plugin.mockcore.javassist.MethodMockerManager
import com.jf.anmocker.plugin.mockcore.javassist.ReplaceAgentMocker
import com.jf.mocker.anotations.IClassMocker
import javassist.ClassPool
import javassist.CtClass
import javassist.CtField
import javassist.Modifier
import org.objectweb.asm.Type

/**
 * @Class: Test
 * @Description:
 * @author:
 * @Date: 2022/9/26
 */
class Test {
}

fun main(args: Array<String>) {
    //var list = FileFilter.getClassFileList("D:\\DevelopWorkSpace\\AndroidProjects\\Mocker\\app\\build\\intermediates\\javac\\debug\\classes")
    //println(list?.size)

    test7()

    println("test finished")
}

fun test7(){
    val methodDescriptor = "(Ljava/lang/String;IDFZBJC)V"
    val types = Type.getArgumentTypes(methodDescriptor)
    types.forEach {
        println("className:" + it.className)
        println("descriptor:" + it.descriptor)
    }

}

fun test6(){
    println("IClassMocker >>> ${Type.getDescriptor(IClassMocker::class.java)}")
    println("IClassMocker >>> ${Type.getDescriptor(String::class.java)}")
}

fun test5(){
    var className = "androidx.coordinatorlayout.R\$style"
    var className2 = "androidx.coordinatorlayout.R"
    var className3 = "androidx.test.coordinatorlayout.R\$style"
    var className4 = "androidx.test.coordinatorlayout.R"
    //val regex = "\\+.R(\$\\*)".toRegex()
    val regex = """(\w*(.\w*))*.R(\$\w*)?""".toRegex()
    println("$className match >>>>>> ${regex.matches(className)}")
    println("$className find >>>>>> ${regex.find(className)?.value}")
    println("$className2 match >>>>>> ${regex.matches(className2)}")
    println("$className2 find >>>>>> ${regex.find(className2)?.value}")
    println("$className3 match >>>>>> ${regex.matches(className3)}")
    println("$className3 find >>>>>> ${regex.find(className3)?.value}")
    println("$className4 match >>>>>> ${regex.matches(className4)}")
    println("$className4 find >>>>>> ${regex.find(className4)?.value}")
}

fun test4(){
    val pathAbs = "D:\\DevelopWorkSpace\\AndroidWorkSpace\\android-mocker\\app\\build\\intermediates\\javac\\debug\\classes"
    val mClassPool : ClassPool = ClassPool.getDefault()
    mClassPool.appendClassPath(pathAbs)
    val targetName = "com.jf.mocker.MyTestClass"
    val targetCls = mClassPool[targetName]
    println(targetCls)
    var indexField = quireAgentIndexFiled(targetCls)
    val indexValue = indexField.constantValue as Int
    println(indexValue)
    targetCls.removeField(indexField)
    indexField = quireAgentIndexFiled(targetCls, indexValue + 1)
    targetCls.removeField(indexField)
    indexField = quireAgentIndexFiled(targetCls, indexValue + 2)
    println(indexField.constantValue)
    targetCls.writeFile(pathAbs);
    targetCls.detach()
}

fun test3(){
    val pathAbs = "D:\\DevelopWorkSpace\\AndroidWorkSpace\\android-mocker\\app\\build\\intermediates\\javac\\debug\\classes"
    val mClassPool : ClassPool = ClassPool.getDefault()
    mClassPool.appendClassPath(pathAbs)
    val targetName = "com.jf.mocker.MyTestClass"
    val targetCls = mClassPool[targetName]
    val memberInjectMocker = MethodMockerManager(mClassPool)
    val anoName = "com.jf.mocker.mock.MyMocker"
    val anoCls = mClassPool.getOrNull(anoName)
    val classMocker = anoCls.getAnnotation(IClassMocker::class.java)
    if(classMocker is IClassMocker) {
        memberInjectMocker.mockerClassMethods(targetCls, mutableListOf(AnoEntity(classMocker, anoCls)))
    }
    targetCls.writeFile(pathAbs);
    anoCls.detach()
    targetCls.detach()
}

fun test2(){
    val pathAbs = "D:\\DevelopWorkSpace\\AndroidProjects\\Mocker\\app\\build\\intermediates\\javac\\debug\\classes";
    val injector = AMInjector(null)
    injector.collectClassFileFromDir(pathAbs)
    //開始处理注入替代
    injector.injectCollectClasses()
}

fun test1(){
    try{
        val pathAbsKt = "D:\\DevelopWorkSpace\\AndroidProjects\\Mocker\\app\\build\\tmp\\kotlin-classes\\debug";
        val pathAbs = "D:\\DevelopWorkSpace\\AndroidProjects\\Mocker\\app\\build\\intermediates\\javac\\debug\\classes";
        val mainClass = "com.jf.mocker.MyKtTestClass"
        val mainClass2 = "com.jf.mocker.MyMocker"
        val mainClass3 = "com.jf.mocker.MyTestClass"
        //findClass(pathAbsKt, mainClass)
        findClass(pathAbs, mainClass2)
    }catch (e: Exception){
        e.printStackTrace()
    }
}

fun findClass(pathAbs : String, className : String){
    println(pathAbs)
    val mClassPool : ClassPool = ClassPool.getDefault()
    mClassPool.appendClassPath(pathAbs)
    val tempCls = mClassPool[className]
    println(tempCls)
    val classAnnotations = tempCls.annotations
    println("MyMockerInjector >>> classMocker annotations >>> ${classAnnotations.size}")
    //for (ano in classAnnotations){
    //    println("MyMockerInjector >>> classMocker ano >>> $ano")
    //}
    val classMocker = tempCls.getAnnotation(IClassMocker::class.java)
    println("MyMockerInjector >>> classMocker value >>> $classMocker")
    if(classMocker != null && classMocker is IClassMocker){
        println("MyMockerInjector >>> collectClassFile[annotation] >>> ${classMocker.value}")
    }else{
        println("MyMockerInjector >>> collectClassFile[class] >>> $className")
    }
}

fun quireAgentIndexFiled(targetCls : CtClass, initValue : Int = 0) : CtField {
    var filed = MethodMockerManager.getDeclaredFiled(targetCls, ReplaceAgentMocker.AGENT_INDEX)
    if(filed == null){
        filed = CtField(CtClass.intType, ReplaceAgentMocker.AGENT_INDEX, targetCls)
        filed.modifiers = Modifier.PRIVATE + Modifier.STATIC + Modifier.FINAL
        targetCls.addField(filed, CtField.Initializer.constant(initValue))
    }
    return filed
}